package com.googlecode.crowdin.maven;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;

import com.googlecode.crowdin.maven.tool.SortedProperties;

/**
 * Aggregate the translations of this project with crowdin
 * 
 * @goal aggregate
 * @phase generate-resources
 * @threadSafe
 */
public class AggregateCrowdinMojo extends AbstractMojo {

	private static final String DEFAULT_LANG = "en";

	public static final String COMMENT = "This file is automatically generated. Please do not edit this file. "
			+ "If you'd like to change the content please use crowdin";

	/**
	 * The directory where the generated resource files will be stored. The
	 * directory will be registered as a resource root of the project such that
	 * the generated files will participate in later build phases like packaing.
	 * 
	 * @parameter expression=
	 *            "${project.build.directory}/generated-resources/messages-aggregated"
	 * @required
	 */
	private File resourceAggregatedOutputDirectory;

	/**
	 * The directory where the messages can be fund.
	 * 
	 * @parameter expression="${project.basedir}/src/main/crowdin"
	 * @required
	 */
	protected File messagesOutputDirectory;

	public void setResourceAggregatedOutputDirectory(File resourceAggregatedOutputDirectory) {
		this.resourceAggregatedOutputDirectory = resourceAggregatedOutputDirectory;
	}

	public void setMessagesOutputDirectory(File messagesOutputDirectory) {
		this.messagesOutputDirectory = messagesOutputDirectory;
	}

	public void execute() throws MojoExecutionException, MojoFailureException {
		if (messagesOutputDirectory.exists()) {
			getLog().info("Aggregating all message properties from dependencies");

			String[] langFolders = messagesOutputDirectory.list();

			SortedProperties defaultProperties = new SortedProperties();

			for (String langFolder : langFolders) {
				if (langFolder.equals(DEFAULT_LANG)) {
					File langFold = new File(messagesOutputDirectory, langFolder);
					defaultProperties.putAll(aggregatePropertiesFolder(langFold, langFolder, null));
				}
			}

			for (String langFolder : langFolders) {
				if (!langFolder.startsWith(".") && !langFolder.equals(DEFAULT_LANG)) {
					File langFold = new File(messagesOutputDirectory, langFolder);
					if (langFold.isDirectory()) {
						aggregatePropertiesFolder(langFold, langFolder, defaultProperties);
					}
				}
			}

		} else {
			getLog().info("Crowdin folder does not exist (" + messagesOutputDirectory + "). Call pull before.");
		}
	}

	private SortedProperties aggregatePropertiesFolder(File langFolder, String lang, SortedProperties defaultProperties)
			throws MojoExecutionException {
		SortedProperties properties = new SortedProperties();
		if (defaultProperties != null) {
			properties.putAll(defaultProperties);
		}

		getLog().info("Aggregate properties for lang " + lang);
		addAllProperties(properties, langFolder);

		File propertiesFile = new File(resourceAggregatedOutputDirectory, "messages_" + lang + ".properties");
		try {
			propertiesFile.getParentFile().mkdirs();
			FileOutputStream out = new FileOutputStream(propertiesFile);
			properties.store(out, COMMENT);
			out.close();
		} catch (IOException e) {
			throw new MojoExecutionException("Failed to save " + propertiesFile, e);
		}

		return properties;
	}

	private void addAllProperties(SortedProperties properties, File folder) throws MojoExecutionException {
		File[] files = folder.listFiles();
		for (File file : files) {
			if (!file.getName().startsWith(".")) {
				if (file.isDirectory()) {
					addAllProperties(properties, file);
				} else {
					getLog().info("Adding " + file);
					SortedProperties someProperties = new SortedProperties();
					try {
						InputStream inStream = new FileInputStream(file);
						someProperties.load(inStream);
						inStream.close();
					} catch (IOException e) {
						throw new MojoExecutionException("Failed to load " + file, e);
					}
					properties.putAll(someProperties);
				}
			}
		}
	}

}
